home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nfsmount / nfsIO.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-11  |  13.5 KB  |  449 lines

  1. /*
  2.  * nfsIO.c --
  3.  * 
  4.  *    I/O procedures for NFS files.
  5.  *
  6.  * Copyright 1988 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /sprite/src/cmds/nfsmount/RCS/nfsIO.c,v 1.13 91/09/10 19:24:27 mottsmth Exp $ SPRITE (Berkeley)";
  17. #endif not lint
  18.  
  19. #include "stdio.h"
  20.  
  21. #include "nfs.h"
  22. #include "sys/stat.h"
  23. #include "kernel/fsdm.h"
  24. #include "sig.h"
  25.  
  26.  
  27. /*
  28.  * Service switch that the pdev library will use for the pseudo-device
  29.  * connections to each NFS file.
  30.  */
  31. Pdev_CallBacks nfsFileService = {
  32.     NULL,             /* PDEV_OPEN - only for pseudo-devices */
  33.     NfsRead,            /* PDEV_READ */
  34.     NfsWrite,            /* PDEV_WRITE */
  35.     NfsIoctl,            /* PDEV_IOCTL */
  36.     NfsClose,             /* PDEV_CLOSE */
  37.     NfsGetAttrStream,        /* PDEV_GET_ATTR - called on open pfs streams */
  38.     NfsSetAttrStream,        /* PDEV_SET_ATTR - called on open pfs streams */
  39. };
  40.  
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * NfsClose --
  47.  *
  48.  *    Default procedure is called when an PDEV_CLOSE request is
  49.  *    received over an service stream.
  50.  *
  51.  * Results:
  52.  *    Returns SUCCESS and the select state of the pseudo-device.
  53.  *
  54.  * Side effects:
  55.  *    Free's up the handle slot used to remember the open file.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59. /*ARGSUSED*/
  60. int
  61. NfsClose(streamPtr)
  62.     Pdev_Stream *streamPtr;
  63. {
  64.     register Fs_FileID *fileIDPtr = (Fs_FileID *)streamPtr->clientData;
  65.     register nfs_fh *handlePtr;
  66.     register int status = SUCCESS;
  67.  
  68.     if (fileIDPtr->minor >= 0 && fileIDPtr->minor < nfsFileTableSize) {
  69.     if (nfsFileTable[fileIDPtr->minor] != (NfsOpenFile *)NULL) {
  70.         free((char *)nfsFileTable[fileIDPtr->minor]->handlePtr);
  71.         AUTH_DESTROY(nfsFileTable[fileIDPtr->minor]->authPtr);
  72.         free((char *)nfsFileTable[fileIDPtr->minor]);
  73.         nfsFileTable[fileIDPtr->minor] = (NfsOpenFile *)NULL;
  74.     } else {
  75.         printf("NfsClose: no open file for file ID <%d,%d,%d,%d>\n",
  76.         fileIDPtr->type,
  77.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  78.         status = EINVAL;
  79.     }
  80.     free((char *)fileIDPtr);
  81.     } else {
  82.     printf("NfsClose: bad fileID <%d,%d,%d,%d>\n", fileIDPtr->type,
  83.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  84.     status = EINVAL;
  85.     }
  86.     return(status);
  87. }
  88.  
  89. /*
  90.  *----------------------------------------------------------------------
  91.  *
  92.  * NfsRead --
  93.  *
  94.  *    Read from an NFS file.
  95.  *
  96.  * Results:
  97.  *    The number of bytes read.
  98.  *
  99.  * Side effects:
  100.  *    Do the read.
  101.  *
  102.  *----------------------------------------------------------------------
  103.  */
  104. /*ARGSUSED*/
  105. int
  106. NfsRead(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
  107.     Pdev_Stream *streamPtr;    /* Private data */
  108.     Pdev_RWParam *readPtr;    /* Return - how much data was generated */
  109.     Boolean *freeItPtr;        /* In/Out indicates if *bufferPtr is malloc'd */
  110.     int *selectBitsPtr;        /* Return - the select state of the pdev */
  111.     Pdev_Signal *sigPtr;    /* Return - signal to return, if any */
  112. {
  113.     register Fs_FileID *fileIDPtr = (Fs_FileID *)streamPtr->clientData;
  114.     register nfs_fh *handlePtr;
  115.     register int status = NFS_OK;
  116.     register int bytesToRead = readPtr->length;
  117.     register int toRead;
  118.     register Address buffer = readPtr->buffer;
  119.     NfsState *nfsPtr;
  120.     readargs readArgs;
  121.     readres readResult;
  122.  
  123.     if (fileIDPtr->minor >= 0 && fileIDPtr->minor < nfsFileTableSize) {
  124.     handlePtr = nfsFileTable[fileIDPtr->minor]->handlePtr;
  125.     nfsPtr = (NfsState *)fileIDPtr->serverID;
  126.     nfsPtr->nfsClnt->cl_auth = nfsFileTable[fileIDPtr->minor]->authPtr;
  127.     if (fileIDPtr->type == TYPE_FILE) {
  128.         /*
  129.          * Reading from a regular file.  Use standard read RPC.
  130.          * Tell the XDR routines about our pre-allocated buffer.
  131.          */
  132.         readPtr->length = 0;
  133.         readArgs.totalcount = 0;    /* unused by protocol */
  134.         bcopy((char *)handlePtr, (char *)&readArgs.file, sizeof(nfs_fh));
  135.         while (bytesToRead > 0 && status == NFS_OK) {
  136.         toRead = (bytesToRead > NFS_MAXDATA) ? NFS_MAXDATA :
  137.                             bytesToRead;
  138.         readResult.readres_u.reply.data.data_len = toRead;
  139.         readResult.readres_u.reply.data.data_val = buffer;
  140.     
  141.         readArgs.offset = readPtr->offset;
  142.         readArgs.count = toRead;
  143.     
  144.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_READ, xdr_readargs,
  145.             &readArgs, xdr_readres, &readResult, nfsTimeout)
  146.                 != RPC_SUCCESS) {
  147.             clnt_perror(nfsPtr->nfsClnt, "NFSPROC_READ");
  148.             status = EINVAL;
  149.         } else {
  150.             status = readResult.status;
  151.             if (status == NFS_OK) {
  152.             if (toRead > readResult.readres_u.reply.data.data_len) {
  153.                 /*
  154.                  * Short read.
  155.                  */
  156.                 readPtr->length +=
  157.                 readResult.readres_u.reply.data.data_len;
  158.                 break;
  159.             } else {
  160.                 toRead = readResult.readres_u.reply.data.data_len;
  161.                 readPtr->length += toRead;
  162.                 readPtr->offset += toRead;
  163.                 buffer += toRead;
  164.                 bytesToRead -= toRead;
  165.             }
  166.             } else {
  167.             status = NfsStatusMap(status);
  168.             }
  169.         }
  170.         }
  171.     } else if (fileIDPtr->type == TYPE_SYMLINK) {
  172.         /*
  173.          * Use the NFS READLINK procedure to read the link value.
  174.          */
  175.         readlinkres        readLinkResult;
  176.  
  177.         readLinkResult.readlinkres_u.data = buffer;
  178.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_READLINK, xdr_nfs_fh,
  179.             handlePtr, xdr_readlinkres,
  180.             &readLinkResult, nfsTimeout) != RPC_SUCCESS) {
  181.         clnt_perror(nfsPtr->nfsClnt, "NFSPROC_READLINK");
  182.         status = EINVAL;
  183.         } else {
  184.         status = readLinkResult.status;
  185.         if (status == NFS_OK) {
  186.             readPtr->length = strlen(readLinkResult.readlinkres_u.data);
  187.         } else {
  188.             status = NfsStatusMap(status);
  189.         }
  190.         }
  191.     } else {
  192.         /*
  193.          * We have to use the NFS READDIR procedure to read a directory.
  194.          * There are two tricks required.  First we have to
  195.          * save the nfscookie that is returned by the READDIR so we can
  196.          * use it again on the next call to read from the directory.  This
  197.          * trick only works with sequential reading of directories.  The
  198.          * second trick is no biggie, we just have to convert from the
  199.          * linked list returned by the XDR routines to a Sprite format
  200.          * directory.
  201.          */
  202.         readdirargs readDirArgs;
  203.         readdirres readDirResult;
  204.  
  205.         bcopy((char *)handlePtr, (char *)&readDirArgs.dir, sizeof(nfs_fh));
  206.         if (readPtr->offset == 0) {
  207.         bzero((char *)&readDirArgs.cookie, sizeof(nfscookie));
  208.         } else {
  209.         NfsFindCookie(fileIDPtr, readPtr->offset, &readDirArgs.cookie);
  210.         }
  211.         readDirArgs.count = readPtr->length;
  212.         bzero((char *)&readDirResult, sizeof(readdirres));
  213.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_READDIR, xdr_readdirargs,
  214.             &readDirArgs, xdr_readdirres, &readDirResult, nfsTimeout)
  215.                 != RPC_SUCCESS) {
  216.         clnt_perror(nfsPtr->nfsClnt, "NFSPROC_READDIR");
  217.         status = EINVAL;
  218.         readPtr->length = 0;
  219.         } else {
  220.         status = readDirResult.status;
  221.         if (status != NFS_OK) {
  222.             status = NfsStatusMap(status);
  223.             readPtr->length = 0;
  224.         } else {
  225.             NfsToSpriteDirectory(&readDirResult.readdirres_u.reply,
  226.             readPtr->offset, &readPtr->length, buffer, fileIDPtr);
  227.         }
  228.         }
  229.     }
  230.     } else {
  231.     printf("NfsRead: bad fileID <%d,%d,%d,%d>\n", fileIDPtr->type,
  232.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  233.     readPtr->length = 0;
  234.     status = EINVAL;
  235.     }
  236.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  237.     return(status);
  238. }
  239.  
  240. /*
  241.  *----------------------------------------------------------------------
  242.  *
  243.  * NfsWrite --
  244.  *
  245.  *    Write to an NFS file.  This is a thin layer on top of the
  246.  *    basic RPC.  This could be enhanced to pass the data block
  247.  *    off to a subordinate writing process.
  248.  *
  249.  * Results:
  250.  *    None.
  251.  *
  252.  * Side effects:
  253.  *    None.
  254.  *
  255.  *----------------------------------------------------------------------
  256.  */
  257.  
  258. /*ARGSUSED*/
  259. int
  260. NfsWrite(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
  261.     Pdev_Stream *streamPtr;    /* Private data */
  262.     int async;            /* ought not to be TRUE in NFS! */
  263.     Pdev_RWParam *writePtr;    /* Information about the write and writer */
  264.     int *selectBitsPtr;        /* Result - select state of the pseudo-device */
  265.     Pdev_Signal *sigPtr;    /* Result - signal to return, if any */
  266. {
  267.     register Fs_FileID *fileIDPtr = (Fs_FileID *)streamPtr->clientData;
  268.     register nfs_fh *handlePtr;
  269.     NfsState *nfsPtr;
  270.     register int status = NFS_OK;
  271.     register int bytesToWrite;
  272.     register int toWrite;
  273.     int openFlags;
  274.     writeargs writeArgs;
  275.     attrstat attrStat;
  276.  
  277.     if (fileIDPtr->minor >= 0 && fileIDPtr->minor < nfsFileTableSize) {
  278.     handlePtr = nfsFileTable[fileIDPtr->minor]->handlePtr;
  279.     openFlags = nfsFileTable[fileIDPtr->minor]->openFlags;
  280.     nfsPtr = (NfsState *)fileIDPtr->serverID;
  281.     nfsPtr->nfsClnt->cl_auth = nfsFileTable[fileIDPtr->minor]->authPtr;
  282.  
  283.     if (openFlags & FS_APPEND) {
  284.         /*
  285.          * Find out how big the file in order to approximate
  286.          * append-mode writing.
  287.          */
  288.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_GETATTR, xdr_nfs_fh,
  289.             handlePtr, xdr_attrstat, &attrStat, nfsTimeout)
  290.                 != RPC_SUCCESS) {
  291.         clnt_perror(nfsPtr->nfsClnt, "NFSPROC_GETATTR");
  292.         status = FAILURE;
  293.         goto exit;
  294.         } else {
  295.         status = attrStat.status;
  296.         if (status == NFS_OK) {
  297.             writePtr->offset = attrStat.attrstat_u.attributes.size;
  298.         } else {
  299.             status = NfsStatusMap(status);
  300.             goto exit;
  301.         }
  302.         }
  303.     }
  304.     bcopy((char *)handlePtr, (char *)&writeArgs.file, sizeof(nfs_fh));
  305.     bytesToWrite = writePtr->length;
  306.     writePtr->length = 0;
  307.     writeArgs.beginoffset = 0;    /* unused by NFS protocol */
  308.     writeArgs.totalcount = 0;    /* unused by NFS protocol */
  309.     while (bytesToWrite > 0 && status == NFS_OK) {
  310.         writeArgs.offset = writePtr->offset;
  311.         toWrite = (bytesToWrite > NFS_MAXDATA) ? NFS_MAXDATA : bytesToWrite;
  312.         writeArgs.data.data_len = toWrite;
  313.         writeArgs.data.data_val = writePtr->buffer;
  314.     
  315.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_WRITE, xdr_writeargs,
  316.             &writeArgs, xdr_attrstat, &attrStat, nfsTimeout)
  317.             != RPC_SUCCESS) {
  318.         clnt_perror(nfsPtr->nfsClnt, "NFSPROC_WRITE");
  319.         status = EINVAL;
  320.         } else {
  321.         status = attrStat.status;
  322.         if (status != NFS_OK) {
  323.             status = NfsStatusMap(status);
  324.         } else {
  325.             NfsCacheAttributes(fileIDPtr,
  326.                     &attrStat.attrstat_u.attributes);
  327.             bytesToWrite -= toWrite;
  328.             writePtr->buffer += toWrite;
  329.             writePtr->length += toWrite;
  330.             writePtr->offset += toWrite;
  331.         }
  332.         }
  333.     }
  334.     if (async && (bytesToWrite > 0)) {
  335.         fprintf(stderr, "Warning: short async NFS write\n");
  336.     }
  337.     } else {
  338.     printf("NfsWrite: bad fileID <%d,%d,%d,%d>\n", fileIDPtr->type,
  339.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  340.     writePtr->length = 0;
  341.     status = EINVAL;
  342.     }
  343. exit:
  344.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  345.     return(status);
  346. }
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * NfsIoctl --
  352.  *
  353.  *    Take special actions on an NFS file.  This handles truncation,
  354.  *    and could be modified to handle locking, some day, some how.
  355.  *
  356.  * Results:
  357.  *    IOC_TRUNCATE maps to a SetAttributes with a short size.
  358.  *
  359.  * Side effects
  360.  *    None to internal data structure.  The I/O controls have various
  361.  *    effects on NFS files.
  362.  *
  363.  *----------------------------------------------------------------------
  364.  */
  365. /*ARGSUSED*/
  366. int
  367. NfsIoctl(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
  368.     Pdev_Stream *streamPtr;
  369.     Pdev_IOCParam *ioctlPtr;
  370.     int *selectBitsPtr;
  371.     Pdev_Signal *sigPtr;
  372. {
  373.     register Fs_FileID *fileIDPtr = (Fs_FileID *)streamPtr->clientData;
  374.     register nfs_fh *handlePtr;
  375.     NfsState *nfsPtr;
  376.     attrstat attrStat;
  377.     int status;
  378.  
  379.     if (fileIDPtr->minor >= 0 && fileIDPtr->minor < nfsFileTableSize) {
  380.     handlePtr = nfsFileTable[fileIDPtr->minor]->handlePtr;
  381.     nfsPtr = (NfsState *)fileIDPtr->serverID;
  382.     nfsPtr->nfsClnt->cl_auth = nfsFileTable[fileIDPtr->minor]->authPtr;
  383.  
  384.     switch (ioctlPtr->command) {
  385.         case IOC_PDEV_SIGNAL_OWNER: {
  386.         /*
  387.          * Special test of IOC_PDEV_SIGNAL_REPLY.
  388.          * We have the user program ask for it!
  389.          */
  390.         sigPtr->signal = SIG_SUSPEND;
  391.         sigPtr->code = SIG_NO_CODE;
  392.         status = SUCCESS;
  393.         break;
  394.         }
  395.         case IOC_TRUNCATE: {
  396.         sattrargs sattrArgs;
  397.  
  398.         if (ioctlPtr->inBufSize < sizeof(int) ||
  399.             ioctlPtr->inBuffer == NULL) {
  400.             status = GEN_INVALID_ARG;
  401.             break;
  402.         }
  403.         bcopy((char *)handlePtr, (char *)&sattrArgs.file,
  404.             sizeof(nfs_fh));
  405.         sattrArgs.attributes.mode = -1;
  406.         sattrArgs.attributes.uid = -1;
  407.         sattrArgs.attributes.gid = -1;
  408.         sattrArgs.attributes.size = *(int *)ioctlPtr->inBuffer;
  409.         sattrArgs.attributes.atime.seconds = -1;
  410.         sattrArgs.attributes.atime.useconds = -1;
  411.         sattrArgs.attributes.mtime.seconds = -1;
  412.         sattrArgs.attributes.mtime.useconds = -1;
  413.         if (clnt_call(nfsPtr->nfsClnt, NFSPROC_SETATTR, xdr_sattrargs,
  414.                 &sattrArgs, xdr_attrstat, &attrStat, nfsTimeout)
  415.                 != RPC_SUCCESS) {
  416.             clnt_perror(nfsPtr->nfsClnt, "NFSPROC_SETATTR");
  417.             status = EINVAL;
  418.         } else {
  419.             status = NfsStatusMap((int) attrStat.status);
  420.         }
  421.         break;
  422.         }
  423.         case IOC_GET_FLAGS:
  424.         case IOC_SET_FLAGS:
  425.         case IOC_SET_BITS:
  426.         case IOC_CLEAR_BITS:
  427.         case IOC_REPOSITION:
  428.         case IOC_GET_OWNER:
  429.         case IOC_SET_OWNER:
  430.         case IOC_WRITE_BACK:
  431.         status = SUCCESS;
  432.         break;
  433.         case IOC_LOCK:
  434.         case IOC_UNLOCK:
  435.         case IOC_MAP:
  436.         case IOC_NUM_READABLE:
  437.         default:
  438.         status = GEN_NOT_IMPLEMENTED;
  439.         break;
  440.     }
  441.     } else {
  442.     printf("NfsIoctl: bad fileID <%d,%d,%d,%d>\n", fileIDPtr->type,
  443.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  444.     }
  445.     ioctlPtr->outBufSize = 0;
  446.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  447.     return(status);
  448. }
  449.